package com.yx.sys.service.impl;

import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.yx.common.utils.JwtUtil;
import com.yx.common.vo.Result;
import com.yx.sys.entity.*;
import com.yx.sys.mapper.RoleMapper;
import com.yx.sys.mapper.UserMapper;
import com.yx.sys.mapper.UserRoleMapper;
import com.yx.sys.mapper.VerificationMapper;
import com.yx.sys.service.IMenuService;
import com.yx.sys.service.IUserService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import io.swagger.annotations.Example;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * <p>
 * 用户信息 服务实现类
 * service包含了serviceImpl（service接口的实现类） 是提供给controller 使用的，针对于某些业务将 dao 的对于某些表
 * 的crud进行组合，也就是说间接的和数据库打交道。
 * </p>
 *
 * @author yx
 * @since 2023-02-14
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {
    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Autowired
    private JwtUtil jwtUtil;

    @Resource
    private UserRoleMapper userRoleMapper;

    @Autowired(required = false)
    private UserMapper userMapper;

    @Autowired(required = false)
    private VerificationMapper emailMapper;

    @Autowired
    private IMenuService menuService;
    @Override
    public Map<String, Object> login(User user) {
//        根据用户名和密码查询
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(User::getUsername,user.getUsername());
        User loginUser = this.baseMapper.selectOne(wrapper);
//        结果不为空，且密码匹配，则生成token，并将用户信息存入redis
        if(loginUser != null && passwordEncoder.matches(user.getPassword(), loginUser.getPassword())){
//            暂时用UUID，终极方案是jwt
//            String key = "user:"+ UUID.randomUUID();
//            存入redis
            loginUser.setPassword(null);
//            redisTemplate.opsForValue().set(key,loginUser,30, TimeUnit.MINUTES);
//            创建jwt
            String token = jwtUtil.createToken(loginUser);
//            返回数据
            Map<String,Object> data = new HashMap<>();
            data.put("token",token);

            return data;
        }
        return null;
    }
    @Override
    public Map<String, Object> getUserInfo(String token) {
//        根据token获取用户信息，redis
//        Object obj = redisTemplate.opsForValue().get(token);
//        try catch快捷键 ctrl+alt+t
        User loginUser = null;
        try {
            loginUser = jwtUtil.parseToken(token, User.class);
        } catch (Exception e) {
            e.printStackTrace();
        }
        if(loginUser!=null){
//            User loginUser = JSON.parseObject(JSON.toJSONString(obj),User.class);
            Map<String,Object> data = new HashMap<>();
            data.put("uId",loginUser.getUId());
            data.put("username",loginUser.getUsername());
            data.put("nickname",loginUser.getNickname());
            data.put("uAvatar",loginUser.getUAvatar());
            data.put("uEmail",loginUser.getUEmail());
            data.put("status",loginUser.getStatus());
            data.put("fansNum",loginUser.getFansNum());
//            角色
            List<String> roleList = this.baseMapper.getRoleNameByUserId(loginUser.getUId());
            data.put("roles",roleList);
//            权限列表
            List<Menu> menuList = menuService.getMenuListByUserId(loginUser.getUId());
            data.put("menuList",menuList);
            return data;
        }
        return null;
    }
    @Override
    public void logout(String token) {
//        redisTemplate.delete(token);
    }

//    获取验证码
    @Override
    public Result<?> emailVerification(String uEmail) {
//        Example example = new Example();
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.eq("uEmail",uEmail);
        User user = userMapper.selectOne(wrapper);
//      校验用户表中是否存在此用户
        if(user!=null){
            QueryWrapper<Verification> verificationQueryWrapper = new QueryWrapper<>();
            verificationQueryWrapper.eq("email",uEmail);
            Verification verification = emailMapper.selectOne(verificationQueryWrapper);
//            校验该邮箱是否发送过验证码，即判断数据库中是否有记录
            if(verification!=null){
//                校验用户输入验证码是否

            }else{
                return Result.fail("未获取验证码");
            }

        }else{
            return Result.fail("用户不存在");
        }

        return null;
    }

    @Override
    @Transactional
    public String addUser(User user) {
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.eq("username",user.getUsername()).eq("uEmail",user.getUEmail());
        User selectOne = userMapper.selectOne(wrapper);
        if(selectOne==null){
            //        写入用户表
            this.baseMapper.insert(user);
//        写入用户角色表
            List<Integer> roleIdList = user.getRoleIdList();
            if(roleIdList != null){
                for (Integer roleId:roleIdList) {
                    userRoleMapper.insert(new UserRole(null,user.getUId(),roleId));
                }
            }
            return "新增用户成功";
        }else{
            return "当前用户已存在";
        }

    }

    @Override
    public User getUserById(Integer uId) {
        User user = this.baseMapper.selectById(uId);
        LambdaQueryWrapper<UserRole> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(UserRole::getUId,uId);
        List<UserRole> userRoleList = userRoleMapper.selectList(wrapper);
        List<Integer> roleIdList = userRoleList.stream()
                                               .map(userRole -> {return userRole.getRoleId();})
                                               .collect(Collectors.toList());
        user.setRoleIdList(roleIdList);
        return user;
    }

    @Override
    @Transactional
    public void updateUser(User user) {
//        更新用户表
        this.baseMapper.updateById(user);
//        清除原有角色
        LambdaQueryWrapper<UserRole> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(UserRole::getUId,user.getUId());
        userRoleMapper.delete(wrapper);
//        设置新的角色
        List<Integer> roleIdList = user.getRoleIdList();
        if(roleIdList != null){
            for (Integer roleId:roleIdList) {
                userRoleMapper.insert(new UserRole(null,user.getUId(),roleId));
            }
        }
    }

    @Override
    public void deleteUserById(Integer uId) {
        this.baseMapper.deleteById(uId);
//        清除原有角色
        LambdaQueryWrapper<UserRole> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(UserRole::getUId,uId);
        userRoleMapper.delete(wrapper);
    }

    @Override
    public List<?> getUserByNickname(String nickname) {
//        List<?> list = userMapper.getUserByNickname(nickname);
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.like("nickname",nickname);
        List<User> list = userMapper.selectList(wrapper);
        return list;
    }

    @Override
    public void registerUser(Map<String, ?> user) {
//        1、验证用户名和邮箱是否唯一
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.eq("username",user.get("username")).eq("uEmail",user.get("uEmail"));
        User selectOne = userMapper.selectOne(wrapper);
        System.out.println(selectOne);
        if(selectOne==null){
            User user1 = new User();
            user1.setUsername(user.get("username").toString());
            user1.setPassword(passwordEncoder.encode(user.get("password").toString()));
            user1.setUEmail(user.get("uEmail").toString());
            user1.setUAvatar("http://localhost:3000/image/avatar/avatar.jpg");
            userMapper.insert(user1);
        }
    }

    @Override
    public String resetPassword(Map<String, ?> user) {
        String code = "3m"+UUID.randomUUID().toString().replace("-","").substring(0,6);
        User newUser = new User();
        newUser.setPassword(passwordEncoder.encode(code));
        LambdaUpdateWrapper<User> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(User::getUsername,user.get("username")).eq(User::getUEmail,user.get("uEmail"));
        userMapper.update(newUser,updateWrapper);
        return code;
    }


}
